#include"stdio.h"
#include"string.h"
#include"base64.h"

char Base64Table[64]={
  'A','B','C','D','E','F','G','H',
  'I','J','K','L','M','N','O','P',
  'Q','R','S','T','U','V','W','X',
  'Y','Z','a','b','c','d','e','f',
  'g','h','i','j','k','l','m','n',
  'o','p','q','r','s','t','u','v',
  'w','x','y','z','0','1','2','3',
  '4','5','6','7','8','9','+','/'
};
char URLBase64Table[64]={
  'A','B','C','D','E','F','G','H',
  'I','J','K','L','M','N','O','P',
  'Q','R','S','T','U','V','W','X',
  'Y','Z','a','b','c','d','e','f',
  'g','h','i','j','k','l','m','n',
  'o','p','q','r','s','t','u','v',
  'w','x','y','z','0','1','2','3',
  '4','5','6','7','8','9','-','_'
};

int Base64Encode3(unsigned char *input,int inlen,char *output,int type)
{
    unsigned char b1,b2,b3;
    unsigned char i;
    char *table;
    if(type==TYPEURL)
      table = URLBase64Table;
    else
      table = Base64Table;
    if(inlen<1 || inlen>3)
       return -1; 
    b1 = *input;
    if(inlen==3)
      { 
       b2 = *(input+1);
       b3 = *(input+2);
      }
     else
      {
        if(inlen==2)
          {
            b2 = *(input+1);
            b3 = 0;
          }
        else
          {
            b2 = 0;
            b3 = 0;
          } 
      }     
    i = ((b1&0xfc)>>2);
    *output = table[(i&0x3f)];
    i = ((b1&0x03)<<4)|((b2&0xf0)>>4);
    *(output+1) = table[(i&0x3f)];
    if(inlen==1)
      {
        *(output+2) = BASE64PAD;
        *(output+3) = BASE64PAD;
        return 2;
      } 
    i = ((b2&0x0f)<<2)|((b3&0xc0)>>6);
    *(output+2) = table[(i&0x3f)];
    if(inlen==2)
      {
        *(output+3) = BASE64PAD;
        return 1;
      }
    i = (b3&0x3f);
    *(output+3) = table[i];
    return 0;
    
}

int Base64Encode(unsigned char *input,int inlen,char *output,int *outlen,int type)
{
    int i,j,k;
    char enc[6];
    j = inlen;
    k=0;i=0;
    while(j>3)
     {
       Base64Encode3(input+k,3,enc,type);
       memcpy(output+i,enc,4);
       j-=3;
       k+=3;
       i+=4;
     }
    if(j>0)
     {  
      Base64Encode3(input+k,j,enc,type); 
       memcpy(output+i,enc,4);
      i+=4;
     }
    *(output+i)=0; 
    *outlen = i;
    return i;  
}

int Base64Index(char ch)
{
   if(ch>='A' && ch<='Z')
    return (ch-'A');
   if(ch>='a' && ch<='z')
     return (ch-'a'+26);
   if(ch>='0' && ch<='9')
      return (ch-'0'+52);    
   if(ch=='-' || ch=='+')
     return 62;
   if(ch=='_' || ch=='/')
     return 63;  
   return 64; 
}
int Base64Decode3(char *input,int inlen,unsigned char *output )
{
   unsigned char b[4],bv,bv1,bv2,bv3;
   char *table;
   int i;
   if(inlen<2)
     return -1;
   b[0]=b[1]=b[2]=b[3]=BASE64PAD;
   for(i=0;i<inlen;i++)
     b[i] = input[i];
   i=0;
   bv = Base64Index(b[0]);
   bv1 = Base64Index(b[1]);
   if(bv>63) return -1;
   if(bv1>63)
      return -1;
   *output = (bv<<2)|((bv1&0x30)>>4);
   i++;
   bv2 = Base64Index(b[2]);
   if(bv2>63)
     return i;
   *(output+1) = ((bv1&0x0f)<<4)|((bv2&0x3c)>>2);     
    i++;
    bv3=Base64Index(b[3]);
   if(bv3>63)
      return i;
   *(output+2) = ((bv2&0x03)<<6)|(bv3&0x3f);         
   i++;
   return i;
}

int Base64Decode(char *input,int inlen,unsigned char *output,int *outlen)
{
   int i,j,k,n;
   unsigned char dec[6];
   j=inlen;
   i=0;k=0;
   while(j>4)
    {
       n = Base64Decode3(input+k,4,dec);
       if(n>0)
        {
         memcpy(output+i,dec,n);
         i+=n;
        } 
       j-=4;
       k+=4;  
    }
   n = Base64Decode3(input+k,j,dec);
   if(n>0)
    {
      memcpy(output+i,dec,n);
      i+=n;
    }  
   *outlen = i; 
   return i;
}


